/**
 * created by dqn 2018/3/8 10:13
 */

package main.controller;

import main.entity.Song;
import main.entity.SongCollect;
import main.entity.WebUser;
import main.service.CommentService;
import main.service.SongCollectService;
import main.service.SongService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
public class SongController {
    @Autowired
    SongService songService;
    @Autowired
    SongCollectService songCollectService;
    @Autowired
    CommentService commentService;

    /**
     * 根据歌曲的id查询歌曲信息
     * @param pk
     * @return
     */
    @RequestMapping(value = "/song/get/{pk}",method = RequestMethod.GET)
    public Song getSongByPk(@PathVariable  int pk){
        Song song = songService.getSongById(pk);
        return song;
    }


    /**
     * 获得分类
     *
     * @return map, contains style and language.
     */
    @RequestMapping(value = "/song/category/get/all", method = RequestMethod.GET)
    public Map<String, List<String>> getSongCategory() {
        return songService.getSongCategories();
    }

    /**
     * 上传歌曲
     *
     * @param song      歌曲的文字信息
     * @param session   当前的session,用于权限检验
     * @param imageFile 上传的歌曲封面文件
     * @param songFile  上传的歌曲文件
     * @return json {"result":"permission error/duplicated song name/error/done"}
     * @throws IOException
     */
    @RequestMapping(value = "/song/upload", method = RequestMethod.POST)
    public Map<String, Object> uplaodSong(Song song,
                                          HttpSession session,
                                          @RequestPart("image") MultipartFile imageFile,
                                          @RequestPart("file") MultipartFile songFile) throws IOException {
        Map<String, Object> resultMap = new HashMap<>();
        String key = "result";
        /**
         * 权限
         */
        WebUser webUser = (WebUser) session.getAttribute("user");
        if (webUser == null || !webUser.getPermission().equals("admin")) {
            resultMap.put(key, "permission error");
            return resultMap;
        }

        Song sameNameSong = songService.getSongByName(songFile.getOriginalFilename().substring(0, songFile.getOriginalFilename().indexOf(".")));
        if (sameNameSong != null) {
            resultMap.put(key, "duplicated song name");
            return resultMap;
        }

        Song returnSong = songService.uploadSong(session,song, songFile, imageFile);
        if (returnSong == null) {
            resultMap.put(key, "error");
            return resultMap;
        }
        resultMap.put(key, "done");
        resultMap.put("song", returnSong);
        return resultMap;
    }

    /**
     * 根据歌曲风格查询
     *
     * @param style 风格
     * @param page  第几页，默认1 开始
     * @param size  每页的大小
     * @return [song1, song2, song3..]
     */
    @RequestMapping(value = "/song/get/style/{style}/page/{page}/size/{size}", method = RequestMethod.GET)
    public Map<String, Object> getSongInPageByStyle(@PathVariable String style,
                                                    @PathVariable int page,
                                                    @PathVariable int size) {
        try {
            style = new String(style.getBytes("iso-8859-1"),"utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        if (page < 0) {
            page = 0;
        }
        if (size < 1) {
            size = 1;
        }

        System.out.println(style);

        Map<String, Object> resultMap = new HashMap<>();
        Page<Song> songPage = songService.getSongsInPageByStyle(
                style,
                PageRequest
                        .of(page, size, Sort.Direction.ASC, "name"));
        resultMap.put("totalPage", songPage.getTotalPages());
        resultMap.put("totalSize", songPage.getTotalElements());
        resultMap.put("currentPage", songPage.getNumber() + 1);
        resultMap.put("data", songPage.getContent());
        return resultMap;
    }

    /**
     * 根据语言查询y
     * @param language
     * @param page
     * @param size
     * @return
     */
    @RequestMapping(value = "/song/get/language/{language}/page/{page}/size/{size}", method = RequestMethod.GET)
    public Map<String, Object> getSongInPageLanguage(@PathVariable String language,
                                                    @PathVariable int page,
                                                    @PathVariable int size) {
        try {
            language = new String(language.getBytes("iso-8859-1"),"utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        if (page < 0) {
            page = 0;
        }
        if (size < 1) {
            size = 1;
        }

        System.out.println(language);

        Map<String, Object> resultMap = new HashMap<>();
        Page<Song> songPage = songService.getSongsInPageByLanguage(
                language,
                PageRequest.of(page, size, Sort.Direction.ASC, "name"));
        resultMap.put("totalPage", songPage.getTotalPages());
        resultMap.put("totalSize", songPage.getTotalElements());
        resultMap.put("currentPage", songPage.getNumber() + 1);
        resultMap.put("data", songPage.getContent());
        return resultMap;
    }

    /**
     * 获取所有的歌曲，分页
     */
    /**
     * 获取全部歌曲，分页发送
     *
     * @param page
     * @param size
     * @return json [{song1},{song2}..]
     */
    @RequestMapping(value = "/song/get/all/page/{page}/size/{size}", method = RequestMethod.GET)
    public Map<String, Object> getAllSongsInPage(@PathVariable int page, @PathVariable int size) {
        Map<String, Object> resultMap = new HashMap<>();
        if (page < 0){
            page = 0;
        }
        Page<Song> songPage = songService.getAll(PageRequest.of(page, size, Sort.Direction.ASC, "name"));
        songPage.getContent().stream().forEach(song -> System.out.println(song.getName()));
        resultMap.put("songs", songPage.getContent());
        resultMap.put("pages", songPage.getTotalPages());
        resultMap.put("size", songPage.getTotalElements());
        // +1 从 0 开始
        resultMap.put("current", songPage.getNumber() + 1);
        return resultMap;
    }

    /**
     * 点击量最高的
     *
     * @param size
     * @return json [{song1},{song2}..]
     */
    @RequestMapping(value = "/song/get/top-click/size/{size}", method = RequestMethod.GET)
    public List<Song> getTopClickSongs(@PathVariable int size) {
        return songService.getAllByClickLimitedTo(size);
    }

    /**
     * delete song by id
     *
     * @param id
     * @return json {"result":"done/failed"}
     */
    @RequestMapping(value = "/song/del/{id}", method = RequestMethod.GET)
    public Map<String, String> deleteMusicById(@PathVariable int id,HttpSession httpSession) {
        Map<String, String> resultMap = new HashMap<>();
        String key = "result";

        Song song = songService.getSongById(id);
        File songFile = new File(httpSession.getServletContext().getRealPath(song.getFileUri()));
        File imgFile = new File(httpSession.getServletContext().getRealPath(song.getFileUri()));

        try {
            imgFile.delete();
            songFile.delete();

            // 删除收藏
            songCollectService.deleteBySongId(song.getPk());
            commentService.delCommentsBySongPk(song.getPk());
        }catch (Exception e){
            resultMap.put(key, "failed");
            return resultMap;
        }



        if (songService.deleteById(id)) {
            resultMap.put(key, "done");
        } else {
            resultMap.put(key, "failed");
        }
        return resultMap;
    }

    /**
     * 获取最新的N首歌曲
     * @param limit
     * @return
     */
    @RequestMapping(value = "/song/new/{limit}",method = RequestMethod.GET)
    public List<Song> getNeweastSongsLimitedBy(@PathVariable int limit){
        return songService.getNewSongsLimit(limit);
    }

    /**
     * 获取播放列表，根据seeion用户喜欢的音乐和最新的返回
     * @param httpSession
     * @return [song1,song2..]
     */
    @RequestMapping(value = "/song/playlist",method = RequestMethod.GET)
    public List<Song> getPlayList(HttpSession httpSession){
        List<Song> songs = new ArrayList<>();
        WebUser webUser = (WebUser) httpSession.getAttribute("user");
        if (webUser != null){
            List<Song> likeSongs = songCollectService.getSongCollectsByUserId(webUser.getPk())
                    .stream()
                    .map(songCollect -> songCollect.getSongId())
                    .map(id->songService.getSongById(id))
                    .collect(Collectors.toList());
            songs.addAll(likeSongs);
        }
        songs.addAll(songService.getNewSongsLimit(50));
        songs = songs.stream().distinct().collect(Collectors.toList());
        return songs;
    }

    /**
     * 添加喜欢的音乐到收藏
     * @param httpSession
     * @param song
     * @return
     */
    @RequestMapping(value = "/song/like/{song}" ,method = RequestMethod.GET)
    public Map<String,Object> likeSong(HttpSession httpSession,@PathVariable int song){
        Map<String,Object> result = new HashMap<>();
        // TODO: 2018/3/17 add favorite to SongCollect.
        String key = "result";
        WebUser webUser = (WebUser) httpSession.getAttribute("user");
        if (webUser == null){
            result.put(key,"permission error");
            return result;
        }
        SongCollect songCollect = songCollectService.likeSong(webUser.getPk(),song);
        result.put(key,"done");
        result.put("sc",songCollect);
        return result;
    }

    /**
     * 取消喜欢一个音乐
     * @param httpSession
     * @param song
     * @return
     */
    @RequestMapping(value = "/song/dislike/{song}",method = RequestMethod.GET)
    public Map<String,Object> dislike(HttpSession httpSession,@PathVariable int song){
        Map<String,Object> resultMap = new HashMap<>();
        String key = "result";
        WebUser webUser = (WebUser) httpSession.getAttribute("user");
        if (webUser == null){
            resultMap.put(key,"permission error");
            return resultMap;
        }
        if (songCollectService.dislikeSong(webUser.getPk(),song)){
            resultMap.put(key,"done");
        }else {
            resultMap.put(key,"failed");
        }
        return resultMap;
    }

    /**
     * 获取用户的收藏列表
     * @param httpSession
     * @return [result:done/failed,[song1,song2..]]
     */
    @RequestMapping(value = "/song/likes",method = RequestMethod.GET)
    public Map<String,Object> getUserLikes(HttpSession httpSession){
        WebUser webUser = (WebUser) httpSession.getAttribute("user");
        Map<String,Object> resultMap = new HashMap<>();
        if (webUser == null){
            resultMap.put("result","failed");
            return resultMap;
        }
        resultMap.put("result","done");
        List<Song> songs = songCollectService.getSongCollectsByUserId(webUser.getPk())
                .stream()
                .map(songCollect -> songCollect.getSongId())
                .map(id->songService.getSongById(id))
                .collect(Collectors.toList());
        resultMap.put("song",songs);
        return resultMap;
    }

    /**
     * 判断是否喜欢某首歌，空用户直接不喜欢
     * @param httpSession
     * @param song
     * @return
     */
    @RequestMapping(value = "/song/is-like/{song}",method = RequestMethod.GET)
    public Map<String,Object> isLike(HttpSession httpSession,@PathVariable int song){
        WebUser webUser = (WebUser) httpSession.getAttribute("user");
        Map<String,Object> map = new HashMap<>();
        String key = "result";
        if (webUser == null) {
            map.put(key,"no");
            return map;
        }
        boolean isLike = songCollectService.isLike(webUser.getPk(),song);
        map.put(key,isLike?"yes":"no");
        return map;
    }

    /**
     * 获取相应用户的喜好列表，
     * 如果用户没有登录，没有个人推荐
     * 只有热门推荐
     * @param httpSession
     * @return
     */
    @RequestMapping(value = "/song/like/tops",method = RequestMethod.GET)
    public Map<String,Object> getSongByUserLikes(HttpSession httpSession){
        Map<String,Object> map = new HashMap<>();
        WebUser webUser = (WebUser) httpSession.getAttribute("user");
        List<Song>  hotTop = songService.getAllByClickLimitedTo(8);
        map.put("hot",hotTop);
        if (webUser == null){
            map.put("special",new ArrayList<>());
            return map;
        }
        List<Song> likes = songCollectService.getSongCollectsByUserId(webUser.getPk())
                .parallelStream()
                .map(songCollect -> songCollect.getSongId())
                .map(songid->songService.getSongById(songid))
                .sorted((a,b)->b.getClick()-a.getClick())
                .collect(Collectors.toList());
        List<Song> specialSongs = new ArrayList<>();
        likes.forEach(like->{
            if (specialSongs.size() < 8){
                specialSongs.addAll(songService.getSongsInPageByStyle(like.getStyle(),PageRequest.of(0,8,Sort.Direction.DESC,"click")).getContent());
            }
        });
        if (specialSongs.size()<8){
            specialSongs.addAll(songService.getNewSongsLimit(20));
        }
        List<Song> tmp = specialSongs.stream().distinct().limit(8).collect(Collectors.toList());
        map.put("special",tmp);
        return map;
    }
}

